package ar.edu.unicen.pladema.vc1.practico3;

import java.io.IOException;

import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;

import ar.edu.unicen.pladema.ui.model.CoordinatesMapping;
import ar.edu.unicen.pladema.ui.model.g3d.Matrix;
import ar.edu.unicen.pladema.ui.model.g3d.MatrixStack;
import ar.edu.unicen.pladema.ui.model.g3d.Triangle;
import ar.edu.unicen.pladema.ui.model.g3d.Vertex;
import ar.edu.unicen.pladema.ui.model.points.ScreenPoint;
import ar.edu.unicen.pladema.vc1.formats.sur.Data3D;
import ar.edu.unicen.pladema.vc1.formats.sur.SUR;
import ar.edu.unicen.pladema.vc1.model.GraphicAttributes;
import ar.edu.unicen.pladema.vc1.practico.PracticoDrawer;

public class P3Enunciado1Drawer extends PracticoDrawer {
	private String lastFileOpened;
	private Data3D data3d;
	private MatrixStack matrixStack;
	private Vertex pluz;
	private CoordinatesMapping cm;
	public P3Enunciado1Drawer(GraphicAttributes ga) {
		super(ga);
		matrixStack = new MatrixStack();
		
		pluz = new Vertex();
		pluz.setX("2");
		pluz.setY("0");
		pluz.setZ("-2");
		
	}

	@Override
	protected void paintControlImpl(PaintEvent e) {
		if (data3d == null) {
			return;
		}
		Data3D transformedData3d = data3d.transform(matrixStack.getTransform());
		transformedData3d.sortTriangles();
		
		double xMin = transformedData3d.minX();
		double xMax = transformedData3d.maxX();
		double yMin = transformedData3d.minY();
		double yMax = transformedData3d.maxY();
		double zMin = transformedData3d.minZ();
		double zMax = transformedData3d.maxZ();
		graphicAttributes.add("RCXmin", xMin).add("RCXmax", xMax)
			.add("RCYmin", yMin).add("RCYmax", yMax)
			.add("RCZmin", zMin).add("RCZmax", zMax);
		if (cm == null) {
			cm = new CoordinatesMapping(400, 400,
				xMin, xMax,
				yMin, yMax, true);
		}
		
		Vertex nLuz = pluz.getNormalized();
		for (Triangle triangle : transformedData3d.getTriangles()) {
			drawTriangle(e.gc, triangle, cm, nLuz);
		}
		drawLight(e.gc, pluz, cm);
	}
	
	private void drawLight(GC gc, Vertex v, CoordinatesMapping cm) {
		int x = cm.reverseX(v.getDX());
		int y = cm.reverseY(v.getDY());
		Color cb = new Color(gc.getDevice(), 255, 255, 255);
		gc.setBackground(cb);
		Color cf = new Color(gc.getDevice(), 0, 0, 0);
		gc.setForeground(cf);
		gc.fillOval(x-6, y-10, 35, 35);
		gc.drawText("LUZ", x, y);
		
	}

	private void drawTriangle(GC gc, Triangle triangle, CoordinatesMapping cm, Vertex nLuz) {
		Vertex v1 = triangle.getVertex1();
		Vertex v2 = triangle.getVertex2();
		Vertex v3 = triangle.getVertex3();
		
		double cosTheta = triangle.getCosTheta(nLuz);
		int r=1;
		int g=-1;
		int b=0;
		//cosTheta = Math.max(0, cosTheta);
		
		int n = (new Double(128 * cosTheta)).intValue();
		n = n +128;
		//if (n > 255) {
		//	System.out.println("WARNING! n vale " + n + " porque el coseno de theta vale " + cosTheta);
		//	n =255;
		//}
		r = n;//Math.max(n*r,0);
		g = n;//Math.max(n*g,0);
		b = n;

		Color cl = getColor(r, g, b);
		gc.setBackground(cl); 
		drawTriangle(gc, v1, v2, v3, cm);
		//gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
		//drawLine(gc, v1, v2, cm);
		//drawLine(gc, v1, v3, cm);
		//drawLine(gc, v2, v3, cm);

	}
	private void drawNormal(GC gc, Triangle triangle, CoordinatesMapping cm) {
		Vertex v1 = triangle.getVertex1();
		Vertex v2 = triangle.getVertex2();
		Vertex v3 = triangle.getVertex3();
		Vertex vN = triangle.getNormal();
		Color cl = new Color(gc.getDevice(), 255, 0, 0);
		gc.setForeground(cl);
		drawLine(gc, v1, vN, cm);
		drawLine(gc, v2, vN, cm);
		drawLine(gc, v3, vN, cm);
	}

	private void drawLine(GC gc, Vertex v1, Vertex v2, CoordinatesMapping cm) {
		int x1 = cm.reverseX(v1.getDX());
		int y1 = cm.reverseY(v1.getDY());
		int x2 = cm.reverseX(v2.getDX());
		int y2 = cm.reverseY(v2.getDY());
		gc.drawLine(x1, y1, x2, y2);
	}
	private void drawTriangle(GC gc, Vertex v1, Vertex v2, Vertex v3, CoordinatesMapping cm) {
		int x1 = cm.reverseX(v1.getDX());
		int y1 = cm.reverseY(v1.getDY());
		int x2 = cm.reverseX(v2.getDX());
		int y2 = cm.reverseY(v2.getDY());
		int x3 = cm.reverseX(v3.getDX());
		int y3 = cm.reverseY(v3.getDY());
		gc.fillPolygon(new int[] {x1,y1,x2,y2,x3,y3});		
	}

	public void movePoint(ScreenPoint from, ScreenPoint to) {
		if (cm == null) return;
		pluz.setDX(cm.translateX(to.getX()));
		pluz.setDY(cm.translateY(to.getY()));
		graphicAttributes.add("XLight", pluz.getDX())
			.add("YLight", pluz.getDY())
			.add("ZLight", pluz.getDZ());
		data3d.setLight(pluz);
	}

	public void doZoom(boolean in) {
		Matrix transform = new Matrix();
		if (in) {
			transform.setEscala(1.1);
		} else {
			transform.setEscala(0.9);
		}
		matrixStack.push(transform);
		
	}

	public void openFile(String string) {
		if (string == null) return;
		if (string.equals(lastFileOpened)) return;
		lastFileOpened = string;
		System.out.println("\nabriendo " + lastFileOpened);
		try {
			this.data3d = SUR.read(string);
			cm = null;
			data3d.setLight(pluz);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
